package serivces

import (
	"context"
	"errors"
	"tcp_server/src/common_util"
	"tcp_server/src/config"
	"tcp_server/src/dao"
	"tcp_server/src/utils"
	"time"
)

type LoginService struct{}

func NewLoginService() *LoginService {
	return &LoginService{}
}

// Login 登录方法
func (s *LoginService) Login(args ...interface{}) (interface{}, error) {

	var rpcLoginRes common_util.RPCLoginResponse

	if len(args) < 2 {
		common_util.ErrorLogger.Printf("Login 方法被调用传入的参数不足: %v", args)
		return nil, errors.New("调用Login 方法所需要参数不足")
	}
	username, ok1 := args[0].(string)
	password, ok2 := args[1].(string)
	if !ok1 || !ok2 {
		common_util.ErrorLogger.Printf("Login 方法被调用传入的参数类型有误：%v", args)
		return nil, errors.New("调用Login 方法所需要参数类型转换错误（所需类型为 string）")
	}

	user, err := dao.GetUserByUsername(username)
	if err != nil {
		common_util.ErrorLogger.Printf("数据库查询出现错误: %v", err)
		rpcLoginRes.Message = "TCP Server 数据库查询出现错误"
		rpcLoginRes.Code = -1
	} else {
		if user == nil || user.Password != password {
			rpcLoginRes.Code = 0
			rpcLoginRes.Message = "用户不存在或账号密码输入错误"
		} else {
			rpcLoginRes.Code = 1
			rpcLoginRes.Token = utils.CreateToken()
			rpcLoginRes.Message = "success"
			s.saveUserMessage(username, rpcLoginRes.Token)
		}
	}
	return rpcLoginRes, nil
}

// saveUserMessage 将生成的Token保存到数据库中，同时保存到Redis
func (s *LoginService) saveUserMessage(username string, token string) {
	expireTime := time.Now().Add(config.TokenExpireTime)
	if err := dao.UpdateToken(username, token, expireTime); err != nil {
		common_util.ErrorLogger.Printf("Token 更新回数据库出现异常：%v", err)
		return
	}
	redisTokenKey := config.RedisUserTokenKey + username
	redisClient := config.Redis
	tokenExpireTime := time.Until(expireTime)
	if err := redisClient.Set(context.Background(), redisTokenKey, token, tokenExpireTime).Err(); err != nil {
		common_util.ErrorLogger.Printf("Token缓存到Redis中出现错误：%v", err)
	}
}
